<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>数据响应式</title>
  </head>
  <body>
    <h3 id="h3Title"></h3>
    <input type="text" id="inputTitle" />

    <script>
      let data = {
        title: '你好mvvm'
      }
      const h3Title = document.getElementById('h3Title')
      const inputTitle = document.getElementById('inputTitle')

      // 收集依赖
      let dep = new Set()

      // 对数据进行劫持，不能把普通对象绑到视图中
      let target = {}
      Object.defineProperty(target, 'title', {
        get() {
          dep.add(h3Title)
          dep.add(inputTitle)
          // return data.title
          return Reflect.get(data, 'title')
        },
        set(newValue) {
          if (data.title !== newValue) {
            // data.title = newValue
            Reflect.set(data, 'title', newValue)
            // 通知更新
            notify()
          }
          return true
        }
      })
      // 获取
      h3Title.innerHTML = target.title
      inputTitle.value = target.title

      // 修改
      inputTitle.oninput = function () {
        target.title = this.value
      }

      // 通知依赖项中的视图要来更新[按需更新 -- 观察者]
      function notify() {
        dep.forEach(item => {
          // 获取元素的标签名称，大写的
          if (item?.nodeName === 'H3') {
            item.innerHTML = target.title
          } else if (item?.nodeName === 'INPUT') {
            item.title = this.value
          } else {
          }
        })
      }
    </script>
  </body>
</html>
